package org.ntu.rtsearch.datacollected;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.json.JSONException;
import org.json.JSONObject;
import org.ntu.rtsearch.utils.CommonLogger;
import org.scribe.model.OAuthRequest;
import org.scribe.model.Response;
import org.scribe.model.Token;
import org.scribe.model.Verb;
import org.scribe.oauth.OAuthService;

public class TweetCollected {
	
	private OAuthService service = Resource.getService();
	
	HashMap<String, String> map = new HashMap<String, String>();
	
	/**
	 * collect tweet data
	 * @throws IOException
	 */
	private void collectTweets() throws IOException {
		BufferedReader userIdReader = new BufferedReader(new FileReader(Constants.USER_ID_FILE_PATH));
		
		int tweetFileIdx = 0;
		// set the writer's buffer to 2MB to improve performance
		BufferedWriter tweetWriter = new BufferedWriter(
				new FileWriter(Constants.TWEET_FILE_PATH + tweetFileIdx++), 2097152);
		
		String userId = null;
		int tokenIdx = 0, cnt = 0, total = 0;
		Token token = Resource.getToken(tokenIdx);
		
		long start = System.currentTimeMillis();
		// traversing the social network
		while((userId = userIdReader.readLine()) != null) {
			OAuthRequest req = new OAuthRequest(Verb.GET, Constants.USER_TIMELINE_URL + userId);
			service.signRequest(token, req);
			
			Response resp = req.send();
			if(resp.getCode() == 200) {
				 tweetWriter.write(resp.getBody() + "\n");
			} else if(resp.getCode() != 400) {
				CommonLogger.logger.info("error code:" + resp.getCode());
				CommonLogger.logger.debug("tweets for user id: " 
						+ userId + " response error");
			}
			
			// limited, change access token
			if(++cnt >= 350 || resp.getCode() == 400) {
				cnt = 0;
				tokenIdx = (tokenIdx + 1) % 20;
				token = Resource.getToken(tokenIdx);
				CommonLogger.logger.info("change access token, count: " + cnt 
						+ ", response code: " + resp.getCode());
				long end = System.currentTimeMillis();
				CommonLogger.logger.info(end - start);
				start = System.currentTimeMillis();
			} 
			
			// divide the tweets into 50 files
			if(++total >= 10000) {
				total = 0;
				tweetWriter.flush();
				tweetWriter.close();
				
				// write to a new file
				tweetWriter = new BufferedWriter(
						new FileWriter(Constants.TWEET_FILE_PATH + tweetFileIdx++), 2097152);
				CommonLogger.logger.info("write to a new file: tweet" + (tweetFileIdx - 1));
			}
			// 7000 times per hour
//			try {
//				TimeUnit.MILLISECONDS.sleep(1);
//			} catch (InterruptedException e) {
//				e.printStackTrace();
//			}
		}
		
		// release resourse
		userIdReader.close();
		tweetWriter.flush();
		tweetWriter.close();
	}
	

	// show the limit message
	public void showLimitStatus() throws JSONException {
		OAuthRequest req4limit = new OAuthRequest(Verb.GET, Constants.LIMIT_STATUS_URL);
		service.signRequest(Resource.getToken(0), req4limit);
		Response resp = req4limit.send();
				
		if(resp.getCode() == 200) {
			JSONObject obj = new JSONObject(resp.getBody());
			String seconds = obj.getString("reset_time_in_seconds");
			String remain = obj.getString("remaining_hits");
			
			map.put(seconds, remain);
						
			for (Map.Entry<String, String> entry : map.entrySet()) {
				System.out.println(entry.getKey() + " : " + entry.getValue());
			}
			
			System.out.println("-------------------------");
		} else if(resp.getCode() == 400) {
			System.out.println("limited");
		} 
		
	}
	
	public static void main(String[] args) {
		TweetCollected col = new TweetCollected();
		CommonLogger.logger.info("start");
		try {
			//col.showLimitStatus();
			col.collectTweets();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
